package com.yonyou.brigade.third_parties.meiya.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.yonyou.brigade.basic_init.enums.ChannelEnum;
import com.yonyou.brigade.basic_init.model.BriChannel;
import com.yonyou.brigade.basic_init.model.IChannelConfig;
import com.yonyou.brigade.basic_init.service.IBriChannelService;
import com.yonyou.brigade.basic_init.service.IUserCenterService;
import com.yonyou.brigade.order_center.model.ThirdResult;
import com.yonyou.brigade.third_parties.common.model.ThirdUser;
import com.yonyou.brigade.third_parties.meiya.constant.MeiyaConstant;
import com.yonyou.brigade.third_parties.meiya.constant.MeiyaResultConstant;
import com.yonyou.brigade.third_parties.meiya.constant.MeiyaSSOConstant;
import com.yonyou.brigade.third_parties.meiya.dao.MeiyaUserMapper;
import com.yonyou.brigade.third_parties.meiya.model.MeiyaConfig;
import com.yonyou.brigade.third_parties.meiya.model.MeiyaUser;
import com.yonyou.brigade.third_parties.meiya.model.third.*;
import com.yonyou.brigade.third_parties.meiya.service.IMeiyaPublicService;
import com.yonyou.brigade.third_parties.meiya.service.IMeiyaUserService;
import com.yonyou.brigade.third_parties.meiya.util.MeiyaUserConvertUtil;
import com.yonyou.brigade.util.operateutil.CompareUtils;
import com.yonyou.ybzboot.starter.common.exception.BusinessException;
import com.yonyou.ybzboot.starter.common.exception.CustomException;
import com.yonyou.ybzboot.starter.common.util.StringUtil;
import com.yonyou.ybzboot.starter.common.util.UrlUtil;
import com.yonyou.ybzboot.uc.dto.UcUserDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 美亚商旅用户服务 实现类
 *
 * @author kangfw5
 * @since 2019-06-11
 */
@Service
@Slf4j
public class MeiyaUserServiceImpl extends ServiceImpl<MeiyaUserMapper, MeiyaUser> implements IMeiyaUserService {
    @Value("${meiya.host.h5}")
    private String h5Host;
    @Value("${meiya.host.pc}")
    private String pcHost;

    @Value("${brigade.url.noaccess}")
    private String brigadeNoAccessUrl;

    private final String TIME_STAMP_FORMAT = "yyyyMMddHHmmssSSS";
    private final String COMPARE_PROPERTIES = "status,certNumber,cnName,companyId,dName,email,enName,holderId,outsidePassengerId,passengerName,staffId";

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private IBriChannelService briChannelService;
    @Autowired
    private IUserCenterService userCenterService;
    @Autowired
    private IMeiyaPublicService meiyaPublicService;

    @Override
    public String getLoginUrl(String tenant, String org, String phone, String pageType, String pcOrH5, String jsonExt) {
        BriChannel briChannel = briChannelService.getEnableInfoByTenantOrg(tenant, org, ChannelEnum.MEIYA.getName());
        if (null == briChannel) {
            return brigadeNoAccessUrl;
        }
        MeiyaConfig meiyaConfig = JSON.parseObject(briChannel.getConfig(), MeiyaConfig.class);
        String companyId = meiyaConfig.getCompanyId();
        UcUserDto ucUserDto = userCenterService.getCompleteUcUserDtoByPhone(phone, tenant);
        if (ucUserDto == null) {
            throw new CustomException("用户信息不存在或未进入用户中心");
        }
        if (BriChannel.SYNCUSER == briChannel.getSyncUser()) {
            // 用户同步，更新操作
            MeiyaUser ucMeiyaUser = MeiyaUserConvertUtil.ucUser2Meiya(tenant, companyId, ucUserDto);
            Wrapper<MeiyaUser> wrapper = new EntityWrapper<>();
            wrapper.eq(MeiyaUser.TENANT, tenant);
            wrapper.eq(MeiyaUser.MOBILE, phone);
            MeiyaUser meiyaUser = this.selectOne(wrapper);
            if (meiyaUser == null) {
                ThirdResult result = syncUsers(meiyaConfig, Collections.singletonList(ucMeiyaUser), briChannel);
                if (result.getSuccess()) {
                    this.insert(ucMeiyaUser);
                }
            } else {
                Map<String, String> compareMap = new HashMap<>();
                String[] compareFields = COMPARE_PROPERTIES.split(",");
                if (compareFields.length > 0) {
                    for (String compareField : compareFields) {
                        compareMap.put(compareField, "");
                    }
                }
                Map<String, Object> compareResult = CompareUtils.getModifyContent(meiyaUser, ucMeiyaUser, compareMap);
                if (compareResult != null && compareResult.size() > 0) {
                    ThirdResult result = syncUsers(meiyaConfig, Collections.singletonList(ucMeiyaUser), briChannel);
                    if (result.getSuccess()) {
                        ucMeiyaUser.setId(meiyaUser.getId());
                        this.updateById(ucMeiyaUser);
                    }
                }
            }
        }
        String staffCode = ucUserDto.getPersonCode();
        String realName = "";
        String key = meiyaConfig.getKey();
        String channel = meiyaConfig.getChannel();
        SimpleDateFormat df = new SimpleDateFormat(TIME_STAMP_FORMAT);
        String timeStamp = df.format(new Date());
        String[] allKeyStrArray = {companyId, staffCode, realName, timeStamp, MeiyaSSOConstant.SSO_ENCRYPTION_METHOD};

        Arrays.sort(allKeyStrArray, String.CASE_INSENSITIVE_ORDER);
        String password = DigestUtils.sha1Hex(allKeyStrArray[0] + allKeyStrArray[1] + allKeyStrArray[2] + allKeyStrArray[3] + allKeyStrArray[4] + key);

        SSOParam ssoParam = new SSOParam(MeiyaSSOConstant.SSO_VERSION, MeiyaSSOConstant.SSO_PLATFORM_H5, MeiyaSSOConstant.SSO_REQUEST_TYPE, channel, timeStamp, staffCode, MeiyaSSOConstant.SSO_ENCRYPTION_METHOD, password, companyId, realName);
        JSONObject params = new JSONObject();
        params.put(MeiyaSSOConstant.SSO_REQUEST, ssoParam);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.setAccept(MediaType.parseMediaTypes(MediaType.ALL_VALUE));

        HttpEntity<String> entity = new HttpEntity<>("dataJson=" + params.toJSONString(), headers);
        String h5BaseUrl = StringUtil.isNotEmpty(meiyaConfig.getH5BaseUrl()) ? meiyaConfig.getH5BaseUrl() : h5Host;
        String ssoResult = restTemplate.postForObject(h5BaseUrl + MeiyaConstant.H5_SSO_URI + "?timestamp=" + timeStamp, entity, String.class);
        // 返回结果处理，得到单点userInfo
        MeiyaSSOInfoDTO meiyaSsoInfo = JSON.parseObject(handleResult(ssoResult), MeiyaSSOInfoDTO.class);
        if (meiyaSsoInfo == null) {
            log.error("美亚商旅单点登录失败,租户{}手机号{}单点结果{}", tenant, phone, ssoResult);
            throw new BusinessException("美亚商旅单点登录失败");
        }
        String sessionId = meiyaSsoInfo.getSessionID();
        String userId = meiyaSsoInfo.getUserID();
        String policyCompanyCode = meiyaSsoInfo.getPolicyCompanyCode();
        // 拼接首页跳转URL
        IndexParam indexParam = new IndexParam(companyId, sessionId, userId, channel, MeiyaSSOConstant.INDEX_VERSION, pcOrH5, policyCompanyCode);
        String data = UrlUtil.getURLEncoderString(JSON.toJSONString(indexParam));
        return h5BaseUrl + MeiyaConstant.H5_INDEX_URI + "?data=" + data;
    }

    private String handleResult(String ssoResult) {
        try {
            JSONObject result = JSON.parseObject(ssoResult);
            if (MeiyaResultConstant.RESULT_SUCCESS.equals(result.getString(MeiyaResultConstant.H5_SSO_RESULT_FLAG))) {
                JSONObject userInfo = Optional.ofNullable(result.getJSONObject(MeiyaResultConstant.H5_SSO_RESULT_CONTENT))
                        .map(ct -> ct.getJSONObject(MeiyaResultConstant.H5_SSO_RESULT_CONTENT_D))
                        .map(d -> d.getJSONObject(MeiyaResultConstant.H5_SSO_RESULT_CONTENT_D_USERINFO)).orElse(new JSONObject());

                return userInfo.toJSONString();
            }
        } catch (Exception e) {
            return null;
        }
        return null;
    }

    @Override
    public ThirdResult syncUsers(IChannelConfig channelConfig, List<ThirdUser> userList) {
        MeiyaConfig meiyaConfig = (MeiyaConfig) channelConfig;
        String token = meiyaPublicService.getToken(meiyaConfig);

        JSONObject params = new JSONObject();
        params.put(MeiyaResultConstant.PC_SSO_RESULT_SESSION_ID, token);
        JSONArray syncPsgList = new JSONArray();
        for (ThirdUser thirdUser : userList) {
            MeiyaUser meiyaUser = (MeiyaUser) thirdUser;
            syncPsgList.add(convertUser(meiyaUser));
        }
        params.put("SyncPsgList", syncPsgList);
        params.put("companyId", meiyaConfig.getCompanyId());

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> entity = new HttpEntity<>(params.toJSONString(), headers);

        String pcBaseUrl = StringUtil.isNotEmpty(meiyaConfig.getPcBaseUrl()) ? meiyaConfig.getPcBaseUrl() : pcHost;
        String syncUserResult = restTemplate.postForObject(pcBaseUrl + MeiyaConstant.PC_SYNC_PSG_URI, entity, String.class);
        log.info("美亚商旅用户同步结果{}", syncUserResult);
        return handleResult2(syncUserResult);
    }


    @Override
    public ThirdResult syncUsers(IChannelConfig channelConfig, List<ThirdUser> userList, BriChannel briChannel) {
        MeiyaConfig meiyaConfig = (MeiyaConfig) channelConfig;
        String token = meiyaPublicService.getToken(meiyaConfig);

        JSONObject params = new JSONObject();
        params.put(MeiyaResultConstant.PC_SSO_RESULT_SESSION_ID, token);
        JSONArray syncPsgList = new JSONArray();
        for (ThirdUser thirdUser : userList) {
            MeiyaUser meiyaUser = (MeiyaUser) thirdUser;
            syncPsgList.add(convertUser(meiyaUser, briChannel));
        }
        params.put("SyncPsgList", syncPsgList);
        params.put("companyId", meiyaConfig.getCompanyId());
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> entity = new HttpEntity<>(params.toJSONString(), headers);

        String pcBaseUrl = StringUtil.isNotEmpty(meiyaConfig.getPcBaseUrl()) ? meiyaConfig.getPcBaseUrl() : pcHost;
        String syncUserResult = restTemplate.postForObject(pcBaseUrl + MeiyaConstant.PC_SYNC_PSG_URI, entity, String.class);
        log.info("美亚商旅用户同步结果{}", syncUserResult);
        return handleResult2(syncUserResult);
    }


    @Override
    public ThirdResult addUser(IChannelConfig channelConfig, ThirdUser thirdUser) {
        return null;
    }

    @Override
    public ThirdResult addUser(IChannelConfig channelConfig, ThirdUser thirdUser, BriChannel briChannel) {
        return null;
    }


    @Override
    public ThirdResult updateUser(IChannelConfig channelConfig, ThirdUser thirdUser) {
        return null;
    }

    @Override
    public ThirdResult updateUser(IChannelConfig channelConfig, ThirdUser thirdUser, BriChannel briChannel) {
        return null;
    }


    private ThirdResult handleResult2(String syncUserResult) {
        ThirdResult result = new ThirdResult(true);
        try {
            JSONObject resultJson = JSON.parseObject(syncUserResult);
            if (MeiyaResultConstant.PC_SSO_RESULT_CODE_SUCCESS.equals(resultJson.getString(MeiyaResultConstant.PC_SSO_RESULT_CODE))) {
                JSONArray userInfoList = Optional.ofNullable(resultJson.getJSONArray(MeiyaResultConstant.PC_SYNC_PASSENGER_LIST))
                        .orElse(new JSONArray());
                result.setData(userInfoList);
                result.setMsg(resultJson.getString("description"));
            } else {
                result.setSuccess(false);
                result.setMsg(resultJson.getString("description"));
            }
        } catch (Exception e) {
            result.setSuccess(false);
            result.setMsg("美亚商旅同步用户接口返回异常" + syncUserResult);
        }
        return result;
    }

    private SyncPsgDTO convertUser(MeiyaUser meiyaUser) {
        SyncPsgDTO psg = new SyncPsgDTO();
        psg.setIsCreateLoginUser(true);
        psg.setIsLeave(meiyaUser.getStatus() == 0);
        psg.setIsRankMapping(false);
        psg.setPwd("brigade2019");

        PassengerInfo passengerInfo = new PassengerInfo();
//        //证件信息
//        if (!StringUtils.isEmpty(meiyaUser.getCertNumber())) {
//            CreditCard certificate = new CreditCard();
//            certificate.setCertType(meiyaUser.getCertType());
//            certificate.setCertNumber(meiyaUser.getCertNumber());
//            passengerInfo.setCertificatesList(Collections.singletonList(certificate));
//        }
        passengerInfo.setCnName(meiyaUser.getCnName());
        passengerInfo.setCompanyId(meiyaUser.getCompanyId());
        passengerInfo.setDName(meiyaUser.getdName());
        passengerInfo.setEmail(meiyaUser.getEmail());
        passengerInfo.setEnName(meiyaUser.getEnName());
        passengerInfo.setMobile(meiyaUser.getMobile());
        passengerInfo.setOutsidePassengerId(meiyaUser.getOutsidePassengerId());
        passengerInfo.setPassengerName(meiyaUser.getPassengerName());
        passengerInfo.setPassengerType(meiyaUser.getPassengerType());
        passengerInfo.setStaffId(meiyaUser.getStaffId());
        passengerInfo.setUserName(meiyaUser.getUserName());
        psg.setPassengerInfo(passengerInfo);

        return psg;
    }

    private SyncPsgDTO convertUser(MeiyaUser meiyaUser, BriChannel briChannel) {
        SyncPsgDTO psg = new SyncPsgDTO();
        psg.setIsCreateLoginUser(true);
        psg.setIsLeave(meiyaUser.getStatus() == 0);

        psg.setPwd("brigade2019");

        PassengerInfo passengerInfo = new PassengerInfo();

        //是否同步职务职级
        if (BriChannel.SYNCRANK == briChannel.getSyncRank()){
            psg.setIsRankMapping(true);
            passengerInfo.setHolderId(meiyaUser.getHolderId());
        }else {
            psg.setIsRankMapping(false);
        }

        //证件信息
//        if (!StringUtils.isEmpty(meiyaUser.getCertNumber())) {
//            CreditCard certificate = new CreditCard();
//            certificate.setCertType(meiyaUser.getCertType());
//            certificate.setCertNumber(meiyaUser.getCertNumber());
//            passengerInfo.setCertificatesList(Collections.singletonList(certificate));
//        }
        passengerInfo.setCnName(meiyaUser.getCnName());
        passengerInfo.setCompanyId(meiyaUser.getCompanyId());
        passengerInfo.setDName(meiyaUser.getdName());
        passengerInfo.setEmail(meiyaUser.getEmail());
        passengerInfo.setEnName(meiyaUser.getEnName());
        passengerInfo.setMobile(meiyaUser.getMobile());
        passengerInfo.setOutsidePassengerId(meiyaUser.getOutsidePassengerId());
        passengerInfo.setPassengerName(meiyaUser.getPassengerName());
        passengerInfo.setPassengerType(meiyaUser.getPassengerType());
        passengerInfo.setStaffId(meiyaUser.getStaffId());
        passengerInfo.setUserName(meiyaUser.getUserName());
        psg.setPassengerInfo(passengerInfo);

        return psg;
    }

}
